﻿// AtlControl.h: CAtlControl 的声明
#pragma once
#include "resource.h"       // 主符号
#include <atlctl.h>
#include "AtlTest_i.h"
#include "_IAtlControlEvents_CP.h"

#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Windows CE 平台(如不提供完全 DCOM 支持的 Windows Mobile 平台)上无法正确支持单线程 COM 对象。定义 _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA 可强制 ATL 支持创建单线程 COM 对象实现并允许使用其单线程 COM 对象实现。rgs 文件中的线程模型已被设置为“Free”，原因是该模型是非 DCOM Windows CE 平台支持的唯一线程模型。"
#endif

using namespace ATL;



// CAtlControl
class ATL_NO_VTABLE CAtlControl :
    public CComObjectRootEx<CComSingleThreadModel>,
    public IDispatchImpl<IAtlControl, &IID_IAtlControl, &LIBID_AtlTestLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
    public IOleControlImpl<CAtlControl>,
    public IOleObjectImpl<CAtlControl>,
    public IOleInPlaceActiveObjectImpl<CAtlControl>,
    public IViewObjectExImpl<CAtlControl>,
    public IOleInPlaceObjectWindowlessImpl<CAtlControl>,
    public IConnectionPointContainerImpl<CAtlControl>,
    public CProxy_IAtlControlEvents<CAtlControl>,
    public IProvideClassInfo2Impl<&CLSID_AtlControl, &__uuidof(_IAtlControlEvents), &LIBID_AtlTestLib>,
    public CComCoClass<CAtlControl, &CLSID_AtlControl>,
    public CComControl<CAtlControl>
{
public:
    CAtlControl()
    {
    }

    DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE | OLEMISC_CANTLINKINSIDE |
        OLEMISC_INSIDEOUT | OLEMISC_ACTIVATEWHENVISIBLE | OLEMISC_SETCLIENTSITEFIRST)

    DECLARE_REGISTRY_RESOURCEID(IDR_ATLCONTROL)

    BEGIN_COM_MAP(CAtlControl)
        COM_INTERFACE_ENTRY(IAtlControl)
        COM_INTERFACE_ENTRY(IDispatch)
        COM_INTERFACE_ENTRY(IViewObjectEx)
        COM_INTERFACE_ENTRY(IViewObject2)
        COM_INTERFACE_ENTRY(IViewObject)
        COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)
        COM_INTERFACE_ENTRY(IOleInPlaceObject)
        COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)
        COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
        COM_INTERFACE_ENTRY(IOleControl)
        COM_INTERFACE_ENTRY(IOleObject)
        COM_INTERFACE_ENTRY(IConnectionPointContainer)
        COM_INTERFACE_ENTRY(IProvideClassInfo)
        COM_INTERFACE_ENTRY(IProvideClassInfo2)
    END_COM_MAP()

    BEGIN_PROP_MAP(CAtlControl)
        PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
        PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
    END_PROP_MAP()

    //
    //  __if_not_exists(_atl_conn_classtype)
    //  {
    //      typedef x _atl_conn_classtype;
    //  }
    //
    //  static const ATL::_ATL_CONNMAP_ENTRY* GetConnMap(_Out_opt_ int* pnEntries) {
    //      static const ATL::_ATL_CONNMAP_ENTRY _entries[] = {
    //

    BEGIN_CONNECTION_POINT_MAP(CAtlControl)
    //
    //          {offsetofclass(ATL::_ICPLocator<&iid>, _atl_conn_classtype)- offsetofclass(ATL::IConnectionPointContainerImpl<_atl_conn_classtype>, _atl_conn_classtype)},
    //
        CONNECTION_POINT_ENTRY(__uuidof(_IAtlControlEvents))

    //
    //          __if_exists(GetAttrConnMap) { {(DWORD_PTR)-2}, {(DWORD_PTR)GetAttrConnMap }, } 
    //          {(DWORD_PTR)-1}
    //      }; 
    //
    //      if (pnEntries) 
    //      { 
    //          __if_exists(GetAttrConnMap) 
    //          { 
    //              GetAttrConnMap(pnEntries); 
    //              * pnEntries += sizeof(_entries) / sizeof(ATL::_ATL_CONNMAP_ENTRY) - 3; 
    //          } 
    //          __if_not_exists(GetAttrConnMap) 
    //          { 
    //              * pnEntries = sizeof(_entries) / sizeof(ATL::_ATL_CONNMAP_ENTRY) - 1; 
    //          } 
    //      } 
    //      return _entries; 
    //  }
    //

    END_CONNECTION_POINT_MAP()

    BEGIN_MSG_MAP(CAtlControl)
        CHAIN_MSG_MAP(CComControl<CAtlControl>)
        DEFAULT_REFLECTION_HANDLER()
        MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
    END_MSG_MAP()

    // IViewObjectEx
    DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE)

    // IAtlControl
public:
    HRESULT OnDraw(ATL_DRAWINFO& di)
    {
        RECT& rc = *(RECT*)di.prcBounds;
        // 将剪辑区域设置为 di.prcBounds 指定的矩形
        HRGN hRgnOld = nullptr;
        if (GetClipRgn(di.hdcDraw, hRgnOld) != 1)
            hRgnOld = nullptr;
        bool bSelectOldRgn = false;

        HRGN hRgnNew = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);

        if (hRgnNew != nullptr)
        {
            bSelectOldRgn = (SelectClipRgn(di.hdcDraw, hRgnNew) != ERROR);
        }

        Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom);
        SetTextAlign(di.hdcDraw, TA_CENTER | TA_BASELINE);
        LPCTSTR pszText = _T("AtlControl");
#ifndef _WIN32_WCE
        TextOut(di.hdcDraw,
            (rc.left + rc.right) / 2,
            (rc.top + rc.bottom) / 2,
            pszText,
            lstrlen(pszText));
#else
        ExtTextOut(di.hdcDraw,
            (rc.left + rc.right) / 2,
            (rc.top + rc.bottom) / 2,
            ETO_OPAQUE,
            nullptr,
            pszText,
            ATL::lstrlen(pszText),
            nullptr);
#endif

        if (bSelectOldRgn)
            SelectClipRgn(di.hdcDraw, hRgnOld);

        DeleteObject(hRgnNew);

        return S_OK;
    }


    DECLARE_PROTECT_FINAL_CONSTRUCT()

    HRESULT FinalConstruct()
    {
        return S_OK;
    }

    void FinalRelease()
    {
    }

    LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
};

OBJECT_ENTRY_AUTO(__uuidof(AtlControl), CAtlControl)
